package com.xlh.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xlh.common.Result;
import com.xlh.common.ResultEnum;
import com.xlh.constant.UserConstant;
import com.xlh.exception.SmsException;
import com.xlh.exception.ValidateCodeException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 登录失败时，自定义的返回结果
 *
 * @author cheer
 */
@Component
public class RestAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {

        Result result = Result.error(ResultEnum.LOGIN_FAILED);
        if (exception instanceof BadCredentialsException || exception instanceof UsernameNotFoundException) {
            result = Result.error(ResultEnum.USER_INFO_MATCH_FAILED);
        }
        if (exception instanceof ValidateCodeException) {
            result = Result.error(ResultEnum.VERIFICATION_CODE_ERROR, exception.getMessage());
        }
        if (exception instanceof DisabledException) {
            result = Result.error(ResultEnum.ACCOUNT_NOT_EXIST);
        }
        if (exception instanceof LockedException) {
            result = Result.error(ResultEnum.ACCOUNT_EXPIRED);
        }

        if (exception instanceof SmsException) {
            String tel = (String) request.getSession().getAttribute(UserConstant.MOBILE_TEL_SESSION_KEY);
            result = new Result(ResultEnum.SMS_CODE_ERROR.getCode(), exception.getMessage(),
                    StringUtils.isNoneBlank(tel) ?
                            tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2") : null);
        } else {
            // 设置session中code失败次数
            setSessionValue(request);
        }

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.getWriter().println(objectMapper.writeValueAsString(result));
        response.getWriter().flush();
    }

    private void setSessionValue(HttpServletRequest request) {
        HttpSession session = request.getSession(true);

        Integer sessionFailNum = (Integer) request.getSession().getAttribute(UserConstant.CODE_FAIL_NUM);
        if (sessionFailNum != null) {
            try {
                session.removeAttribute(UserConstant.CODE_FAIL_NUM);
                session.setAttribute(UserConstant.CODE_FAIL_NUM, sessionFailNum + 1);
            } catch (NumberFormatException e) {
                session.setAttribute(UserConstant.CODE_FAIL_NUM, 1);
            }
        } else {
            session.setAttribute(UserConstant.CODE_FAIL_NUM, 1);
        }

    }

}
